﻿using System;

using System.Collections.Generic;
using System.Text;
using Silvermoon.Controls.Interfaces;
using Silvermoon.Animations;
using Silvermoon.Core;

namespace Silvermoon.Controls.Base
{
    public abstract class FormBase : Control, IForm, ICompositeControl
    {
        private bool formVisible;
        private int transitionDuration = DialogBase.DefaultDuration;

        #region methods

        protected override void PreLayout()
        {
            if (!Margin.IsEmpty) LayoutEngine.Layout(this, Screen.Size);
            base.PreLayout();
        }

        #endregion
        #region Props

        /// <summary>
        /// Gets the transition mode that the dialog is currently performing, if in a transition.
        /// You can use this value on a derived OnTransitionProgress method.
        /// </summary>
        protected TransitionMode CurrentTransition { get; private set; }

        /// <summary>
        /// Gets or sets whether the form is visible, or in what transition state to change if in a transition.
        /// </summary>
        public new bool Visible
        {
            get { return formVisible; }
            set
            {
                if (formVisible != value)
                {
                    if (value) Show(); else Hide();
                }
            }
        }

        /// <summary>
        /// Gets or sets how long a transition between shown and hidden will take.
        /// </summary>
        public int TransitionDuration { get { return transitionDuration; } set { transitionDuration = value; } }

        #endregion
        #region IForm Members

        /// <summary>
        /// Shows the form.
        /// </summary>
        public virtual void Show()
        {
            if (!formVisible)
            {
                OnShowing();
                formVisible = true;
                Screen.Attach(this);
                OnShown();
                Focus();
            }
        }

        /// <summary>
        /// Hides the form
        /// </summary>
        public virtual void Hide()
        {
            if (formVisible)
            {
                OnHiding();
                formVisible = false;
                Screen.Detach(this);
                OnHidden();
            }
        }

        /// <summary>
        /// Shows the from using a transition.
        /// </summary>
        /// <param name="mode">The transition mode to apply.</param>
        public virtual void Show(TransitionMode mode)
        {
            if (!Visible)
            {
                formVisible = true;
                Screen.Attach(this);
                CurrentTransition = mode;
                OnShowing();
                PreLayout();
                Transition.InvokeAsync(new Control[] { this }, mode, transitionDuration, 0, (s, e) => OnShown(), OnTransitionProgress);
                Focus();
            }
        }

        /// <summary>
        /// Occurs while the dialog is in transition mode between hiding and showing and vice versa.
        /// </summary>
        protected virtual void OnTransitionProgress(object sender, AnimEventArgs e)
        {
        }


        /// <summary>
        /// Hides the from using a transition.
        /// </summary>
        /// <param name="mode">The transition mode to apply.</param>
        public virtual void Hide(TransitionMode mode)
        {
            if (Visible)
            {
                formVisible = false;
                CurrentTransition = mode;
                OnHiding();
                Transition.InvokeAsync(new Control[] { this }, mode, transitionDuration, 0, (s, e) => { Screen.Detach(this); OnHidden(); }, OnTransitionProgress);
            }
        }

        /// <summary>
        /// Occurs after a transition when the form is hidden.
        /// </summary>
        protected virtual void OnHidden()
        {
            Screen.Detach(this);
            if (Hidden != null) Hidden(this, EventArgs.Empty);
        }

        /// <summary>
        /// Occurs after a transition when the form is shown.
        /// </summary>
        protected virtual void OnShown()
        {
            if (Shown != null) Shown(this, EventArgs.Empty);
        }

        /// <summary>
        /// Occurs before a transition when the form is about to be hidden.
        /// </summary>
        protected virtual void OnHiding()
        {
            if (Hiding != null) Hiding(this, EventArgs.Empty);
        }

        /// <summary>
        /// Occurs before a transition when the from is about to be shown.
        /// </summary>
        protected virtual void OnShowing()
        {
            if (Showing != null) Showing(this, EventArgs.Empty);
        }

        /// <summary>
        /// Occurs after a transition when the form is shown.
        /// </summary>
        public event EventHandler Shown;

        /// <summary>
        /// Occurs after a transition when the form is hidden.
        /// </summary>
        public event EventHandler Hidden;

        /// <summary>
        /// Occurs before a transition when the from is about to be shown.
        /// </summary>
        public event EventHandler Showing;

        /// <summary>
        /// Occurs after a transition when the form is hidden.
        /// </summary>
        public event EventHandler Hiding;

        #endregion
        #region ICompositeControl members

        public abstract IList<Control> Controls { get; }

        #endregion
    }
}
